<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket Chat Room</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            font-size: 14px;
            color: #333;
        }

        .page-info {
            display: flex;
            justify-content: space-around;
        }

        .room-list {
            padding: 10px;
            border-bottom: 1px solid #f2f2f2;
            font-size: 10px;
            color: #999;
        }

        .section-left {
            width: 80px;
            height: 100vh;
            border-right: 1px dashed #f2f2f2;
            box-sizing: border-box;
        }

        .header {
            display: flex;
            justify-content: space-between;
            padding: 10px;
        }

        .create-room {
            font-size: 12px;
            color: #666;
        }


        .section-right {
            max-width: 750px;
            margin: 0 auto;
            flex: 1;
        }

        .room-info {
            padding: 10px 5px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border: 1px solid #f2f2f2;
        }


        .chat {
            height: 200px;
            max-width: 750px;
            border: 1px solid #f2f2f2;
            overflow-y: auto;
        }

        .chat-item {
            padding: 5px;
            border-bottom: 1px solid #f2f2f2;
        }

        .text-right {
            text-align: right;
            color: #666;
        }

        .txt-input {
            width: 100%;
            padding: 10px;
            border: 1px solid #f2f2f2;
            box-sizing: border-box;
        }

        .sub2 {
            font-size: 12px;
            color: #999;
        }

        .btn-out {
            display: flex;
            justify-content: flex-end;
            align-items: center;
        }

        .btn-submit {
            padding: 5px;
            margin: 0 10px;
        }

        .blank {
            padding: 5px 0;
        }

        .connect-fail {
            padding: 10px;
            border-radius: 5px;
            text-align: center;
            font-size: 12px;
            color: #999;
        }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>

    <div class="page-info" id="app">
        <div class="section-left">
            <div class="header">
                <span>房间列表</span>
                <!-- <span class="create-room">+创建</span> -->
            </div>
            <div class="room-list" v-for="(room,index) in roomList" :key="index" @click="joinRoom(room)">
                <div class="id">房间id: {{room.roomId}}</div>
                <div class="count-online">在线: {{room.count}} 人</div>
            </div>
            <div class="room-list" v-if="roomList.length === 0">加载中...</div>
        </div>
        <div class="section-right">
            <div class="room-info">
                <div class="r-info">
                    房间ID: {{roomInfo.roomId}},人数: {{roomInfo.count}}
                </div>
                <div class="r-info-right">
                    当前用户: {{userInfo.name}}
                </div>
            </div>
            <div class="blank"></div>
            <div class="chat" ref="chat">
                <div class="chat-item" :class="{'text-right': item.userInfo.name === userInfo.name}"
                    v-for="(item,index) in messageList" :key="index">
                    <template v-if="item.userInfo.name !== userInfo.name">{{item.userInfo.name}}: </template>
                    {{item.message.content}}
                </div>
            </div>
            <div class="blank"></div>
            <div>
                <textarea type="text" class="txt-input" v-model="messageVal" placeholder="Type your message..." rows="5"
                    @keyup.enter="keyDown"></textarea>
            </div>
            <div class="blank"></div>
            <div class="btn-out" v-if="connectStatus">
                <span class="sub2">CTRL+ENTER</span>
                <button type="submit" class="btn-submit" @click="sendMessage">SEND</button>
            </div>
            <div v-else class="connect-fail">
                {{connectMsg}}
            </div>
        </div>
    </div>

    <script>

        var app = new Vue({
            el: '#app',
            data: {
                roomInfo: {
                    title: "未知",
                    roomId: '',
                    count: 1
                },
                roomList: [],
                userInfo: {},
                message: {
                    type: 'heartbeat',
                    content: ''
                },

                messageVal: '',

                messageList: [],
                socket: null,
                serverUrl: 'ws://v4.fleetif.com:7101',
                reconnectTimes: 0,//重连次数
                reconnectInterval: 3000, // 重连间隔时间，单位：毫秒
                heartbeatInterval: 60000, // 每30秒发送一次心跳
                heartbeatTimer: null,
                connectStatus: false,
                connectMsg: ""
            },
            mounted() {
                console.log("ok")
                this.init()
            },
            beforeDestroy() {
                clearInterval(this.heartbeatTimer)
            },
            methods: {
                init() {
                    this.userInfo.name = this.getUrlParameter("name") || 'user_' + parseInt(Math.random() * 100)
                    this.roomInfo.roomId = this.getUrlParameter("roomId") || '8888'
                    console.log("===init========", this.userInfo.name, this.roomInfo.roomId)

                    //开始连接
                    this.connect()
                },
                connect() {
                    this.socket = new WebSocket(this.serverUrl);
                    this.socket.onopen = (event) => {
                        this.connectStatus = true
                        console.log('WebSocket connection opened');
                        let msg = {
                            type: 'msg',
                            content: `${this.userInfo.name}加入了房间`,
                            roomUpdate: true
                        }
                        this.socket.send(this.getMessageBean(msg));

                        //心跳
                        this.heartbeatTimer = setInterval(() => {
                            this.socket.send(this.getMessageBean());
                        }, this.heartbeatInterval);
                    };

                    this.socket.onclose = (event) => {
                        console.log('WebSocket connection closed');
                        this.connectStatus = false
                        if (this.reconnectTimes >= 3) {
                            clearInterval(this.heartbeatTimer)
                            console.log("=====重试3次未连接成功======")
                            this.connectMsg = '连接已断开,请刷新页面尝试重新连接'
                        } else {
                            this.connectMsg = '连接已断开,正在尝试重新连接...'
                            setTimeout(() => {
                                console.log('Reconnecting...');
                                this.connect(); // 重新连接
                                this.reconnectTimes++
                            }, this.reconnectInterval);
                        }
                    };

                    this.socket.onerror = (event) => {
                        console.error('WebSocket error', event);
                        this.socket.close(); // 关闭连接
                    };

                    this.socket.onmessage = (event) => {
                        let tempMsg = JSON.parse(event.data)
                        console.log("tempMsg==========", tempMsg)
                        // 处理收到的消息
                        if (tempMsg.message.type === 'heartbeat') {
                            console.log('Received heartbeat ack');
                            this.roomInfo.count = tempMsg.roomInfo.count
                            this.roomList = tempMsg.roomList
                        } else {
                            //声音提示
                            const audio = new Audio('./sound.mp3');
                            audio.play();
                            console.log("====onmessage=====tempMsg====>", tempMsg)
                            this.messageList.push(tempMsg)
                            this.roomInfo.count = tempMsg.roomInfo.count
                            this.$nextTick(() => {
                                const chatDiv = this.$refs.chat;
                                chatDiv.scrollTop = chatDiv.scrollHeight - chatDiv.clientHeight;
                            });

                            if (tempMsg.roomListUpdate || tempMsg.message.roomUpdate) {
                                this.roomList = tempMsg.roomList
                            }
                        }
                    };
                },
                sendMessage() {
                    console.log("sendMessage===========>")
                    try {
                        let message = this.messageVal
                        if (!message && !message.trim()) {
                            return
                        }

                        if (this.checkConnection()) {
                            let msg = {
                                type: 'msg',
                                content: message
                            }
                            this.socket.send(this.getMessageBean(msg));
                            this.messageList.push(this.getMessageBean(msg, null, null, true))
                        } else {
                            alert("连接不可用")
                        }
                        this.messageVal = '';
                        this.$nextTick(() => {
                            const chatDiv = this.$refs.chat;
                            chatDiv.scrollTop = chatDiv.scrollHeight - chatDiv.clientHeight;
                        });
                    } catch (error) {
                        alert("出错了==>" + error)
                    }
                },

                //组装消息实体
                getMessageBean(message, roomInfo, userInfo, flag = false) {
                    let payload = {
                        message: { ...this.message, ...message },
                        roomInfo: { ...this.roomInfo, ...roomInfo },
                        userInfo: { ...this.userInfo, ...userInfo }
                    }
                    if (flag) {
                        console.log("payload", payload)
                        return payload
                    } else {
                        return JSON.stringify(payload)
                    }
                },

                checkConnection() {
                    if (this.socket.readyState === WebSocket.OPEN) {
                        console.log('连接正常，可以发送消息');
                        return true
                    } else if (this.socket.readyState === WebSocket.CONNECTING) {
                        console.log('连接正在建立中');
                        return false
                    } else if (this.socket.readyState === WebSocket.CLOSING) {
                        console.log('连接正在关闭');
                        return false
                    } else if (this.socket.readyState === WebSocket.CLOSED) {
                        console.log('连接已关闭');
                        return false
                    }
                },
                getUrlParameter(paramName) {
                    const urlParams = new URLSearchParams(window.location.search);
                    return urlParams.get(paramName);
                },
                keyDown(e) {
                    if (e.ctrlKey && e.keyCode == 13) {   //用户点击了ctrl+enter触发
                        this.sendMessage();
                    }
                },
                joinRoom(room) {

                    if(this.roomInfo.roomId === room.roomId) return

                    const result = confirm("确认离开当前房间吗?");
                    if (result) {
                        // 用户点击了确认按钮
                        console.log("User confirmed");
                        let lc = window.location
                        lc.href = lc.origin + lc.pathname + `?roomId=${room.roomId}&name=${this.userInfo.name}`
                    } else {
                        // 用户点击了取消按钮
                        console.log("User canceled");
                    }
                }
            }

        })

    </script>
</body>

</html>